{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Numpy\n",
    "\n",
    "NumPy 是一个 Python 包。它代表 “Numeric Python”。它是一个由多维数组对象和用于处理数组的例程集合组成的库。\n",
    "\n",
    "NumPy（Numerical Python）是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵，比Python自身的嵌套列表（nested list structure)结构要高效的多（该结构也可以用来表示矩阵**matrix**），支持大量的维度数组与矩阵运算，此外也针对数组运算提供大量的数学函数库. \n",
    "\n",
    "NumPy（Numeric Python）提供了许多高级的数值编程工具，如：**矩阵数据类型**、**矢量处理**，以及精密的运算库。专为进行严格的数字处理而产生。多为很多**大型金融公司**使用，以及核心的科学计算组织如：Lawrence Livermore，NASA用其处理一些本来使用C++，Fortran或Matlab等所做的任务。\n",
    "\n",
    "NumPy 的前身为 Numeric，最早由 Jim Hugunin 与其它协作者共同开发，2005 年，Travis Oliphant 在 Numeric 中结合了另一个同性质的程序库 Numarray 的特色，并加入了其它扩展而开发了 NumPy。NumPy 为开放源代码并且由许多协作者共同维护开发。\n",
    "\n",
    "#### NumPy 操作\n",
    "\n",
    "使用NumPy，开发人员可以执行以下操作：\n",
    "（1）数组的算数和逻辑运算。\n",
    "（2）傅立叶变换和用于图形操作的例程。\n",
    "（3）与线性代数有关的操作。 NumPy 拥有线性代数和随机数生成的内置函数。\n",
    "\n",
    "#### Numpy 教程\n",
    "\n",
    "- 官方教程 （英文） https://numpy.org/doc/stable/user/quickstart.html\n",
    "- Numpy中文网  https://www.numpy.org.cn/\n",
    "- Numpy 菜鸟教程 https://www.runoob.com/numpy/numpy-tutorial.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'1.15.1'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np   # 导入numpy模块\n",
    "np.__version__"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Numpy的数据结构\n",
    "\n",
    "NumPy 数组的维数称为秩（rank），秩就是轴的数量，即数组的维度，一维数组的秩为 1，二维数组的秩为 2，以此类推。\n",
    "\n",
    "在 NumPy中，每一个线性的数组称为是一个轴（axis），也就是维度（dimensions）。比如说，二维数组相当于是两个一维数组，其中第一个一维数组中每个元素又是一个一维数组。所以一维数组就是 NumPy 中的轴（axis），第一个轴相当于是底层数组，第二个轴是底层数组里的数组。而轴的数量 — 秩，就是数组的维数。\n",
    "\n",
    "很多时候可以声明 axis。axis=0，表示沿着第 0 轴进行操作，即对每一列进行操作；axis=1，表示沿着第1轴进行操作，即对每一行进行操作。\n",
    "\n",
    "Python的numpy中axis=0、axis=1、axis=2解释：\n",
    "https://blog.csdn.net/mahoon411/article/details/114777623\n",
    "\n",
    "NumPy 的数组中比较重要 ndarray 对象属性有：\n",
    "\n",
    "- ndarray.ndim \t  秩，即轴的数量或维度的数量\n",
    "- ndarray.shape   数组的维度，对于矩阵，n 行 m 列\n",
    "- ndarray.size \t  数组元素的总个数，相当于 .shape 中 n*m 的值\n",
    "- ndarray.dtype   ndarray 对象的元素类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.31131476 0.30262946 0.52416098 0.28752365 0.76265411 0.95918521\n",
      " 0.58945999 0.07244318 0.16231055 0.71815638 0.7242092  0.08101359\n",
      " 0.81219226 0.50199541 0.31305341 0.44008441 0.64423707 0.47359699\n",
      " 0.39342721 0.66073795 0.42381325 0.85240682 0.50382143 0.52670339\n",
      " 0.16425283 0.57377306 0.9654485  0.89336036 0.60950241 0.94322525\n",
      " 0.33727622 0.90268218 0.26009899 0.30255876 0.28680793 0.17105089\n",
      " 0.7492128  0.43507575 0.97882185 0.52065398 0.73305207 0.88590537\n",
      " 0.82959878 0.49253956 0.340736   0.01943523 0.26498421 0.02188334\n",
      " 0.93639526 0.7654611 ]\n"
     ]
    }
   ],
   "source": [
    "stock_return = np.random.random(50)  # 假设有5个股票，各10天的收益率是50个随机数\n",
    "  # np.random.random（）：用以产生随机数\n",
    "  #   生成50行浮点数，浮点数都是从0-1中随机\n",
    "  #   https://www.bbsmax.com/A/gVdnq6Ga5W/\n",
    "  #   浮点数详解（一篇彻底学通浮点数）：https://blog.csdn.net/weixin_45863060/article/details/125054244\n",
    "print(stock_return)\n",
    "#type(stock_return)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对于维度的介绍，官网是这么写的“ In NumPy dimensions are called axes”，即维度称为轴。为了更直观的理解，可以将其与现实世界联系起来，比如在平面中即二维的世界中，我们描述一个点的时候，通常使用 x 轴、y 轴，这样就能确定一个点的具体位置了。因此，这里的两个维度，也就跟两个轴对应了起来。如果是立体的三维世界中，我们就会多出一个z轴，以此更加准确的来反映点的位置。所以，我么可以把以上的维度和轴进行等价。\n",
    "\n",
    "什么是秩(rank)？它是指轴的数量，或者维度的数量，是一个标量\n",
    "\n",
    "在下面的例子中，有一个数组 [1,2,1]， 它的维度是1，也就是有一个轴，这个轴的长度是3，而它的秩也为1。这些信息，都可以通过NumPy提供的数组属性来获得。\n",
    "\n",
    "https://zhuanlan.zhihu.com/p/51200424"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.31131476 0.30262946 0.52416098 0.28752365 0.76265411]\n",
      " [0.95918521 0.58945999 0.07244318 0.16231055 0.71815638]\n",
      " [0.7242092  0.08101359 0.81219226 0.50199541 0.31305341]\n",
      " [0.44008441 0.64423707 0.47359699 0.39342721 0.66073795]\n",
      " [0.42381325 0.85240682 0.50382143 0.52670339 0.16425283]\n",
      " [0.57377306 0.9654485  0.89336036 0.60950241 0.94322525]\n",
      " [0.33727622 0.90268218 0.26009899 0.30255876 0.28680793]\n",
      " [0.17105089 0.7492128  0.43507575 0.97882185 0.52065398]\n",
      " [0.73305207 0.88590537 0.82959878 0.49253956 0.340736  ]\n",
      " [0.01943523 0.26498421 0.02188334 0.93639526 0.7654611 ]]\n",
      "stock_return的秩是：\n",
      "2\n",
      "stock_return的维度是：\n",
      "(10L, 5L)\n",
      "stock_return的总个数是：\n",
      "50\n",
      "stock_return的元素类型度是：\n",
      "float64\n"
     ]
    }
   ],
   "source": [
    "# 假设有5个股票，各10天的收益率是50个随机数\n",
    "# 将数据调整成 10 * 5 的维度\n",
    "stock_return = stock_return.reshape(10,5)\n",
    "print(stock_return)\n",
    "print('stock_return的秩是：')\n",
    "print(stock_return.ndim)\n",
    "print('stock_return的维度是：')\n",
    "print(stock_return.shape)\n",
    "print('stock_return的总个数是：')\n",
    "print(stock_return.size)\n",
    "print('stock_return的元素类型度是：')\n",
    "print(stock_return.dtype)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 创建数组\n",
    "\n",
    "数组（Array）是有序的元素序列。\n",
    "\n",
    "- 创建全零或者全1的数组\n",
    "- 创建一个index序列，通常在循环中需要使用\n",
    "- 创建等差数列、等比数列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0. 0. 0. 0. 0.]\n",
      "[[0. 0. 0.]\n",
      " [0. 0. 0.]]\n",
      "float64\n",
      "[[1 1]\n",
      " [1 1]\n",
      " [1 1]]\n"
     ]
    }
   ],
   "source": [
    "# 生成全零或者全一矩阵\n",
    "zeros = np.zeros(5)\n",
    "  # numpy.zeros(shape, dtype=float)\n",
    "  #   https://blog.csdn.net/u011699626/article/details/122193581\n",
    "print(zeros)\n",
    "\n",
    "array = np.zeros([2, 3])\n",
    "print(array)\n",
    "print(array.dtype)\n",
    "\n",
    "ones = np.ones((3,2), dtype = int)\n",
    "  # np.ones（）：https://blog.csdn.net/silent1cat/article/details/119883549\n",
    "print(ones)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在 Python 中，{}、[] 和 () 都是用来表示不同类型的数据结构的符号。\n",
    "- {} 用于表示字典（dictionary）。字典是一种无序的、可变的、可索引的数据结构，它由键值对组成。例如，{'a': 1, 'b': 2} 是一个包含两个键值对的字典。\n",
    "- [] 用于表示列表（list）。列表是一种有序的、可变的、可索引的数据结构，它可以包含任意类型的元素。例如，[1, 2, 3] 是一个包含三个整数元素的列表。\n",
    "- () 用于表示元组（tuple）。元组是一种有序的、不可变的、可索引的数据结构，它可以包含任意类型的元素。例如，(1, 2, 3) 是一个包含三个整数元素的元组。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 5]\n",
      "[1 2 3 4 5]\n"
     ]
    }
   ],
   "source": [
    "# 将列表转成数组 array\n",
    "ones = [1,2,3,4,5]\n",
    "print(ones)\n",
    "\n",
    "new_ones = np.asarray(ones)\n",
    "  # np.array与np.asarray：都是将输入转为矩阵格式。\n",
    "  #   https://blog.csdn.net/xiaomifanhxx/article/details/82498176\n",
    "  #   区别：随着输入的改变np.array的输出不变，而np.asarray的输出在变化。\n",
    "new_ones\n",
    "print(new_ones)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[10 12 14 16 18]\n",
      "[0, 1, 2, 3, 4]\n",
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "7\n",
      "8\n",
      "9\n"
     ]
    }
   ],
   "source": [
    "x = np.arange(10,20,2)  \n",
    "  # 函数返回一个有终点和起点的固定步长的排列\n",
    "print (x)\n",
    "\n",
    "x_list = [y for y in range(5)]\n",
    "  # range（）：产生一系列的数字。当需要叠加一些数字时，可以用到range()函数。\n",
    "  #   基本语法：range(start, stop)\n",
    "  #   range()函数产生的这一系列的数字并不是以列表（list）类型存在的，这样做的目的是为了节省代码所占空间。\n",
    "  #   list(range(0,5))\n",
    "  # for语句的主要作用是遍历容器中的元素\n",
    "  # https://blog.csdn.net/hou09tian/article/details/122985717\n",
    "print(x_list)\n",
    "\n",
    "for i in range(10):\n",
    "    print(i)\n",
    "\n",
    "## np.arange（）\n",
    "# https://blog.csdn.net/qq_41550480/article/details/89390579\n",
    "# 一个参数 默认起点0，步长为1 输出：[0 1 2]\n",
    "a = np.arange(3)\n",
    "# 两个参数 默认步长为1 输出[3 4 5 6 7 8]\n",
    "a = np.arange(3,9)\n",
    "# 三个参数 起点为0，终点为3，步长为0.1 输出[ 0.   0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9  1.   1.1  1.2  1.3  1.4 1.5  1.6  1.7  1.8  1.9  2.   2.1  2.2  2.3  2.4  2.5  2.6  2.7  2.8  2.9]\n",
    "a = np.arange(0, 3, 0.1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 5  6  8 10 11 13 15 16 18 20]\n",
      "[ 5 10 15 20]\n"
     ]
    }
   ],
   "source": [
    "x = np.linspace(5, 20, num = 10, dtype = int)  \n",
    "  # np.linspace（）：定义均匀间隔创建数值序列\n",
    "  #   np.linspace(start, stop, num=50, dtype)\n",
    "  #   https://blog.csdn.net/neweastsun/article/details/99676029\n",
    "print (x)\n",
    "\n",
    "x2 = np.linspace(5, 20, num = 4, dtype = int)  \n",
    "print (x2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[  1   2   4   8  16  32  64 128 256 512]\n",
      "[  8  16  32  64 128 256 512]\n"
     ]
    }
   ],
   "source": [
    "x = np.logspace(0,9,10,base=2, dtype = int)\n",
    "  # np.logspace()：对数等比数列。base 参数意思是取对数的时候 log 的下标\n",
    "  #   np.logspace(start, stop, num=50, base=10.0, dtype=None)\n",
    "n =5\n",
    "print (x)\n",
    "print (x[x>5])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 数组的索引、切片和排序\n",
    "\n",
    "- **索引和切片**\n",
    "ndarray 对象的内容可以通过索引或切片来访问和修改，与 Python 中 list 的切片操作一样。\n",
    "ndarray 数组可以基于 0 - n 的下标进行索引， 通常可以通过冒号分隔切片参数 start:stop:step 来进行切片操作\n",
    "\n",
    ">冒号的解释：如果只放置一个参数，如 [2]，将返回与该索引相对应的单个元素。如果为 [2:]，表示从该索引开始以后的所有项都将被提取。如果使用了两个参数，如 [2:7]，那么则提取两个索引(不包括停止索引)之间的项。\n",
    ">布尔索引：布尔索引通过布尔运算（如：比较运算符）来获取符合指定条件的元素的数组。\n",
    "比如：逻辑运算 (logical operators) 通常用来测试真假值。最常见到的逻辑运算就是循环的处理，用来判断是否该离开循环或继续执行循环内的指令。\n",
    "\n",
    "https://www.numpy.org.cn/user/basics/indexing.html\n",
    "\n",
    "- **排序**\n",
    "NumPy 提供了多种排序的方法。 这些排序函数实现不同的排序算法\n",
    "\n",
    ">numpy.sort()    函数返回输入数组的排序副本\n",
    ">numpy.argsort()  函数返回的是数组值从小到大的索引值\n",
    ">numpy.argmax()和numpy.argmin()函数分别沿给定轴返回最大和最小元素的索引\n",
    ">numpy.where()   函数返回输入数组中满足给定条件的元素的索引\n",
    ">numpy.extract()  函数根据某个条件从数组中抽取元素，返回满条件的元素。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 2 3 4 5 6 7 8 9]\n",
      "[2 4 6]\n",
      "[3 4 5 6 7 8 9]\n",
      "[0 1 2 3 4 5 6 7]\n"
     ]
    }
   ],
   "source": [
    "# 索引和切片\n",
    "#  【Python】numpy数组索引：https://blog.csdn.net/yangjjuan/article/details/105375026\n",
    "a = np.arange(10)  # 返回一个有终点和起点的固定步长的排列（可理解为一个等差数组）\n",
    "a\n",
    "print(a)\n",
    "b = a[2:7:2]       # 从索引 2 开始到索引 7 停止，间隔为 2\n",
    "print(b)\n",
    "c = a[3:]          # 从索引 3 开始到结束\n",
    "print(c)\n",
    "d = a[:-2]         # 从索引 0 开始到倒数第 2\n",
    "print(d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2]\n",
      " [ 3  4  5]\n",
      " [ 6  7  8]\n",
      " [ 9 10 11]]\n",
      "大于 5 的元素是：\n",
      "[ 6  7  8  9 10 11]\n"
     ]
    }
   ],
   "source": [
    "# 索引和切片\n",
    "x = np.array([[  0,  1,  2],[  3,  4,  5],[  6,  7,  8],[  9,  10,  11]])  \n",
    "x\n",
    "print(x)\n",
    "# 现在我们会打印出大于 5 的元素  \n",
    "print  ('大于 5 的元素是：')\n",
    "print (x[x >  5])  # 布尔索引\n",
    "\n",
    "  #   在numpy中，np.array（）创建了一个对象，这个对象就是ndarray\n",
    "  #   数组是一个固定长度的存储相同数据类型的数据结构，数组中的元素被存储在一段连续的内存空间中。\n",
    "  #   https://blog.csdn.net/JianZuoGuang/article/details/104280654\n",
    "  #   ndarray是一个类对象，而array是一个方法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始数组是：\n",
      "[[3 7]\n",
      " [9 1]]\n",
      "\n",
      "\n",
      "按行排序：\n",
      "[[3 7]\n",
      " [1 9]]\n",
      "\n",
      "\n",
      "按列排序：\n",
      "[[3 1]\n",
      " [9 7]]\n"
     ]
    }
   ],
   "source": [
    "# 排序 np.sort\n",
    "x = np.array([[3,7],[9,1]])  \n",
    "  # np.sort()：np.sort(a, axis=-1, kind='quicksort', order=None)。排序\n",
    "  #   axis = 1 按行排序，axis = 0 按列排序，None表示展开来排序，默认值为-1表示沿最后的轴排序\n",
    "print ('原始数组是：')\n",
    "print (x)\n",
    "print ('\\n')\n",
    "print ('按行排序：')\n",
    "print (np.sort(x, axis = 1))\n",
    "print ('\\n')\n",
    "print ('按列排序：')\n",
    "print (np.sort(x, axis = 0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Python的numpy中axis=0、axis=1、axis=2解释：\n",
    "\n",
    "https://blog.csdn.net/mahoon411/article/details/114777623"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始数组是：\n",
      "[3 1 2]\n",
      "\n",
      "\n",
      "对 x 调用 argsort() 函数：\n",
      "[1 2 0]\n",
      "\n",
      "\n",
      "以排序后的顺序重构原数组：\n",
      "[1 2 3]\n"
     ]
    }
   ],
   "source": [
    "# 排序 np.argsort\n",
    "x = np.array([3,  1,  2])  \n",
    "print ('原始数组是：')\n",
    "print (x)\n",
    "print ('\\n')      # 换2行\n",
    "  # print ()      # 换1行\n",
    "print ('对 x 调用 argsort() 函数：')\n",
    "y = np.argsort(x)  \n",
    "  # argsort()：将x中的元素从小到大排列，提取其对应的index(索引)，然后输出到y\n",
    "print (y)\n",
    "print ('\\n') \n",
    "print ('以排序后的顺序重构原数组：')\n",
    "print (x[y])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始数组是：\n",
      "[[30 40 70]\n",
      " [80 20 10]\n",
      " [50 90 60]]\n",
      "\n",
      "\n",
      "调用 argmax() 函数：\n",
      "7\n",
      "\n",
      "\n",
      "展开数组：\n",
      "[30 40 70 80 20 10 50 90 60]\n",
      "\n",
      "\n",
      "沿轴 0 的最大值索引：\n",
      "[1 2 0]\n",
      "\n",
      "\n",
      "沿轴 1 的最大值索引：\n",
      "[2 0 1]\n",
      "\n",
      "\n",
      "调用 argmin() 函数：\n",
      "5\n",
      "\n",
      "\n",
      "展开数组中的最小值：\n",
      "10\n",
      "\n",
      "\n",
      "沿轴 0 的最小值索引：\n",
      "[0 1 1]\n",
      "\n",
      "\n",
      "沿轴 1 的最小值索引：\n",
      "[0 2 0]\n"
     ]
    }
   ],
   "source": [
    "# numpy.argmax() 和 numpy.argmin()\n",
    "#  取出x中元素的最大值所对应的索引\n",
    "#  https://blog.csdn.net/weixin_42755982/article/details/104542538\n",
    "x = np.array([[30,40,70],[80,20,10],[50,90,60]])  \n",
    "print  ('原始数组是：') \n",
    "print (x) \n",
    "print ('\\n') \n",
    "print ('调用 argmax() 函数：') \n",
    "print (np.argmax(x))  # 输出为索引\n",
    "  # n维的数组的 axis 可以取值从 0 到 n-1，其对应的括号层数为从最外层向内递进\n",
    "  #   二维数组的axis：0为列、1为行\n",
    "print ('\\n') \n",
    "print ('展开数组：') \n",
    "print (x.flatten()) \n",
    "  # https://blog.csdn.net/kuan__/article/details/116987162\n",
    "print ('\\n') \n",
    "print ('沿轴 0 的最大值索引：')     # 列\n",
    "maxindex = np.argmax(x, axis =  0)  \n",
    "print (maxindex) \n",
    "print ('\\n') \n",
    "print ('沿轴 1 的最大值索引：')     # 行\n",
    "maxindex = np.argmax(x, axis =  1)  \n",
    "print (maxindex) \n",
    "print ('\\n') \n",
    "\n",
    "print ('调用 argmin() 函数：') \n",
    "minindex = np.argmin(x)  \n",
    "print (minindex) \n",
    "print ('\\n') \n",
    "print ('展开数组中的最小值：') \n",
    "print (x.flatten()[minindex])       # 读出 索引 所对应的数值\n",
    "print ('\\n') \n",
    "print ('沿轴 0 的最小值索引：') \n",
    "minindex = np.argmin(x, axis =  0)  # 列\n",
    "print (minindex) \n",
    "print ('\\n') \n",
    "print ('沿轴 1 的最小值索引：')   \n",
    "minindex = np.argmin(x, axis =  1)  # 行 \n",
    "print (minindex)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始数组是：\n",
      "[[0 1 2]\n",
      " [3 4 5]\n",
      " [6 7 8]]\n",
      "大于 3 的元素的索引：\n",
      "(array([1, 1, 2, 2, 2], dtype=int64), array([1, 2, 0, 1, 2], dtype=int64))\n",
      "使用这些索引来获取满足条件的元素：\n",
      "[4 5 6 7 8]\n",
      "如果数字大于3输出该数字，如果小于3则输出3\n",
      "[[3 3 3]\n",
      " [3 4 5]\n",
      " [6 7 8]]\n"
     ]
    }
   ],
   "source": [
    "# numpy.where() 函数返回输入数组中满足给定条件的元素的索引\n",
    "#   np.where共两种用法:\n",
    "#   第一种、np.where(condition, x, y),即condition为条件,当满足条件输出为x,不满足条件则输出y\n",
    "#   第二种、np.where(condition),只有条件 (condition)，则输出满足条件 (即非0) 元素的坐标 (等价于numpy.nonzero)\n",
    "np.arange(9)\n",
    "np.arange(9).reshape(3,  3)\n",
    "np.arange(9).reshape(3,  3).dtype\n",
    "  # dtype('int32')\n",
    "np.arange(9.).reshape(3,  3)\n",
    "np.arange(9.).reshape(3,  3).dtype\n",
    "  # dtype('float64')\n",
    "    \n",
    "x = np.arange(9).reshape(3,  3)  \n",
    "print ('原始数组是：')\n",
    "print (x)\n",
    "print ( '大于 3 的元素的索引：')\n",
    "y = np.where(x >  3)     # 第二种\n",
    "print (y)\n",
    "print ('使用这些索引来获取满足条件的元素：')\n",
    "print (x[y])\n",
    "\n",
    "# np.where(x) 输出的是5个判断为真的数的坐标，第一个array是横坐标，第二个array是纵坐标\n",
    "\n",
    "y = np.where(x>3, x, 3)  # 第一种\n",
    "print('如果数字大于3输出该数字，如果小于3则输出3')\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始数组是：\n",
      "[[0. 1. 2.]\n",
      " [3. 4. 5.]\n",
      " [6. 7. 8.]]\n",
      "[[0. 1. 0.]\n",
      " [1. 0. 1.]\n",
      " [0. 1. 0.]]\n",
      "按元素的条件值：\n",
      "[[ True False  True]\n",
      " [False  True False]\n",
      " [ True False  True]]\n",
      "使用条件提取元素：\n",
      "[0. 2. 4. 6. 8.]\n"
     ]
    }
   ],
   "source": [
    "# numpy.extract() 函数根据某个条件从数组中抽取元素，返回满足条件的元素。\n",
    "x = np.arange(9.).reshape(3,  3)  \n",
    "print ('原始数组是：')\n",
    "print (x)\n",
    "# 定义条件, 选择偶数元素\n",
    "condition = np.mod(x,2)  ==  0  \n",
    "  # np.mod()的取模计算公式\n",
    "  #  https://blog.csdn.net/ganbelieve/article/details/125604620\n",
    "print ('np.mod(x,2)的结果：')\n",
    "print(np.mod(x,2))\n",
    "print ('按元素的条件值：')\n",
    "print (condition)\n",
    "print ('使用条件提取元素：')\n",
    "print (np.extract(condition, x))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 数组运算\n",
    "\n",
    "- 求和运算\n",
    "- 求极值运算\n",
    "- 求均值\n",
    "- 求方差和标准差"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5.76959207, 4.92694095, 4.01048437, 5.29553425, 4.63436121])"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求5个股票收益率在N天中的和\n",
    "stock_return.sum(axis = 0)\n",
    "  # axis = 0：列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.96823559, 0.8814619 , 0.69284541, 0.93064389, 0.74057245])"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求5个股票收益率在N天中的最大收益\n",
    "stock_return.max(axis = 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.25883143, 0.84881929, 0.74057245, 0.79493054, 0.8814619 ,\n",
       "       0.96823559, 0.86182754, 0.8923388 , 0.833769  , 0.92795277])"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求N天中每天最大收益股票的收益值\n",
    "stock_return.max(axis = 1)\n",
    "  # axis = 1：行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.57695921, 0.4926941 , 0.40104844, 0.52955342, 0.46343612])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求5个股票收益率在N天中的平均收益\n",
    "stock_return.mean(axis = 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "方差\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([0.09714193, 0.10059113, 0.05498448, 0.06757113, 0.03318759])"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求5个股票收益率在N天中的方差\n",
    "print('方差')\n",
    "stock_return.var(axis = 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "标准差\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([0.311676  , 0.31716104, 0.2344877 , 0.25994447, 0.1821746 ])"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求5个股票收益率在N天中的标准差\n",
    "print('标准差')\n",
    "stock_return.std(axis = 0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 矩阵操作\n",
    "\n",
    "- 矩阵的对角线，行列式\n",
    "- 矩阵相乘，矩阵的逆和特征值分解"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "协方差矩阵\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[ 1.        , -0.00552374,  0.11959466,  0.10529631,  0.23271266],\n",
       "       [-0.00552374,  1.        , -0.36748566, -0.59301656,  0.74737238],\n",
       "       [ 0.11959466, -0.36748566,  1.        ,  0.69157851, -0.17272923],\n",
       "       [ 0.10529631, -0.59301656,  0.69157851,  1.        , -0.29269741],\n",
       "       [ 0.23271266,  0.74737238, -0.17272923, -0.29269741,  1.        ]])"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 求5个股票收益率在N天中的协方差矩阵\n",
    "print('协方差矩阵')\n",
    "np.corrcoef(stock_return.T)\n",
    "  # .T：转置\n",
    "  # np.corrcoef（）：https://blog.csdn.net/qq_39514033/article/details/88931639"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 1., 1., 1., 1.])"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 对角线元素\n",
    "stock_corr = np.corrcoef(stock_return.T)  # .T：转置\n",
    "np.diag(stock_corr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.11864646024117902"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 计算行列式\n",
    "#   https://blog.csdn.net/Sun_Raiser/article/details/107304099\n",
    "import numpy.linalg as la\n",
    "stock_corr = np.corrcoef(stock_return.T)\n",
    "la.det(stock_corr)\n",
    "  # numpy.linalg模块中的det函数可以计算矩阵的行列式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([2.45415755, 1.29288797, 0.78880532, 0.1517385 , 0.31241065]),\n",
       " array([[ 0.00594458, -0.67190891, -0.72045271,  0.12241761,  0.12027009],\n",
       "        [-0.56075559, -0.19794095,  0.33533546,  0.69613518,  0.22207769],\n",
       "        [ 0.44869919, -0.40597534,  0.45744988, -0.17462432,  0.62777306],\n",
       "        [ 0.53263294, -0.28858255,  0.24227413,  0.42948016, -0.62439755],\n",
       "        [-0.44776001, -0.51113787,  0.3170818 , -0.53428727, -0.39018623]]))"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 特征值分解 singular value decomposition\n",
    "import numpy.linalg as la\n",
    "stock_corr = np.corrcoef(stock_return.T)\n",
    "la.eig(stock_corr)\n",
    "  # numpy.linalg模块中，eigvals函数可以计算矩阵的特征值，\n",
    "  #   而eig函数可以返回一个包含特征值和对应的特征向量的元组"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
